package net.xumf.web.config;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import net.xumf.domain.master.SystemUser;
import net.xumf.service.master.SystemUserService;
import net.xumf.support.auth.CacheVerification;
import net.xumf.support.auth.CurrentUser;
import net.xumf.support.auth.JWTUtil;
import net.xumf.support.auth.VerificationUtil;
import net.xumf.support.consts.Constants;
import net.xumf.support.enums.CodeEnum;
import net.xumf.support.exception.SystemException;
import net.xumf.support.model.ResponseResult;
import org.apache.http.HttpStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Optional;

@Component
@WebFilter(filterName = "url", urlPatterns = {"/*"})
@Slf4j
public class AuthFilter implements Filter {

    @Autowired
    private SystemUserService userService;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        log.info("初始化权限认证类");
        VerificationUtil.getInstance().setVerificationAbstract(new CacheVerification());
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException, SystemException {

        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse res = (HttpServletResponse) response;
        res.setCharacterEncoding(Constants.Normal.UTF8);
        res.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
        String path = req.getRequestURI();
        if (Lists.newArrayList("/login/action").contains(path)) {
            chain.doFilter(request, response);
            return;
        }
        Cookie[] cookies = Optional.ofNullable(req.getCookies()).orElse(new Cookie[]{});
        Optional<String> tokenOptional = Arrays.stream(cookies).filter(o -> o.getName().equals(Constants.Normal.TOKEN_NAME)).findFirst().map(Cookie::getValue);

        if (!tokenOptional.isPresent()) {
            res.setStatus(HttpStatus.SC_UNAUTHORIZED);
            PrintWriter writer = res.getWriter();
            ResponseResult result = ResponseResult.failure(CodeEnum.TOKEN_ILLEGAL);
            writer.write(JSON.toJSONString(result));
            writer.flush();
            writer.close();
//            throw new SystemException(CodeEnum.TOKEN_ILLEGAL);
        } else {
            String token = tokenOptional.get();
            boolean expired = JWTUtil.isTokenExpired(token);
            if (expired) { // 令牌是否已经过期
                throw new SystemException(CodeEnum.TOKEN_INVALID);
            } else {
                Optional<String> usernameOptional = JWTUtil.getUsername(token);
                if (usernameOptional.isPresent()) {
                    SystemUser user = userService.getByLoginName(usernameOptional.get());
                    if (!JWTUtil.verifyToken(token, user.getSalt().toString())) { // 令牌是否非法
                        throw new SystemException(CodeEnum.TOKEN_ILLEGAL);
                    } else {
                        CurrentUser.instance().set(user);
                        chain.doFilter(request, response);
                    }
                } else {
                    throw new SystemException(CodeEnum.TOKEN_ILLEGAL);
                }
            }
        }
    }

    @Override
    public void destroy() {
        System.out.println("过滤器销毁");
    }
}
